package com.csp.mingyue.common.redis.config;

import cn.hutool.core.util.ObjectUtil;
import com.csp.mingyue.common.redis.handler.KeyPrefixHandler;
import com.csp.mingyue.common.redis.manager.PlusSpringCacheManager;
import com.csp.mingyue.common.redis.support.RedissonProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;

/**
 * Redis 配置
 *
 * @author njy
 */
@Slf4j
@AutoConfiguration
@EnableCaching
@EnableConfigurationProperties(RedissonProperties.class)
@RequiredArgsConstructor
public class RedisConfiguration {

	private final RedissonProperties redissonProperties;

	private final ObjectMapper objectMapper;

	@Bean
	public RedissonAutoConfigurationCustomizer redissonCustomizer() {
		return config -> {
			config.setThreads(redissonProperties.getThreads()).setNettyThreads(redissonProperties.getNettyThreads())
					.setCodec(new JsonJacksonCodec(objectMapper));
			RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
			if (ObjectUtil.isNotNull(singleServerConfig)) {
				// 使用单机模式
				config.useSingleServer()
						// 设置redis key前缀
						.setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix()))
						.setTimeout(singleServerConfig.getTimeout()).setClientName(singleServerConfig.getClientName())
						.setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
						.setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
						.setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
						.setConnectionPoolSize(singleServerConfig.getConnectionPoolSize());
			}
			// 集群配置方式 参考下方注释
			RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig();
			if (ObjectUtil.isNotNull(clusterServersConfig)) {
				config.useClusterServers()
						// 设置redis key前缀
						.setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix()))
						.setTimeout(clusterServersConfig.getTimeout())
						.setClientName(clusterServersConfig.getClientName())
						.setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout())
						.setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize())
						.setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize())
						.setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize())
						.setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize())
						.setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize())
						.setReadMode(clusterServersConfig.getReadMode())
						.setSubscriptionMode(clusterServersConfig.getSubscriptionMode());
			}
			log.info("初始化 redis 配置");
		};
	}

	/**
	 * 自定义缓存管理器 整合 spring-cache
	 */
	@Bean
	public CacheManager cacheManager() {
		return new PlusSpringCacheManager();
	}

	/**
	 * redis集群配置 yml
	 *
	 * --- # redis 集群配置(单机与集群只能开启一个另一个需要注释掉) spring: redis: cluster: nodes: -
	 * 192.168.0.100:6379 - 192.168.0.101:6379 - 192.168.0.102:6379 # 密码 password: #
	 * 连接超时时间 timeout: 10s # 是否开启ssl ssl: false
	 *
	 * redisson: # 线程池数量 threads: 16 # Netty线程池数量 nettyThreads: 32 # 集群配置
	 * clusterServersConfig: # 客户端名称 clientName: ${mingyue.name} # master最小空闲连接数
	 * masterConnectionMinimumIdleSize: 32 # master连接池大小 masterConnectionPoolSize: 64 #
	 * slave最小空闲连接数 slaveConnectionMinimumIdleSize: 32 # slave连接池大小
	 * slaveConnectionPoolSize: 64 # 连接空闲超时，单位：毫秒 idleConnectionTimeout: 10000 #
	 * 命令等待超时，单位：毫秒 timeout: 3000 # 发布和订阅连接池大小 subscriptionConnectionPoolSize: 50 # 读取模式
	 * readMode: "SLAVE" # 订阅模式 subscriptionMode: "MASTER"
	 */

}
